/******************************************************************************
 * Copyright 2024 zhangcong. All Rights Reserved.
 *****************************************************************************/

#include "business/recordbusiness/file/store_file.h"
#include "business/recordbusiness/storetask_manager.h"
#include "minio_client.hpp"
#include "ilogger.hpp"
#include <sstream>
#include <string>

#define MAX_ARRAY_SIZE 256
#define RECORD_INTERVAL 60*3
#define HISTORY_FILE "/data/record_history_file.json"
#define FILE_PATH_STR "/data/sensor/"

static size_t read_file_callback(char *buffer,
                                 size_t size,
                                 size_t nitems,
                                 void *instream)
{
    FILE *fp = reinterpret_cast<FILE *>(instream);
    return fread(buffer, size, nitems, fp);
}

StoreFile::StoreFile()
    :m_Uploadfile_(true), m_uploadData(true), m_handleData(false), m_lastUpfileTime_(0), m_lastUpdataTime_(0),
    m_handleFile(false), m_UploadHistoryfile_(false)
    {}

StoreFile::~StoreFile()
{
    if (m_handleData == true) {
        m_handleData = false;
        m_HandleDataThread_->detach();
    }
    if (m_handleFile == true) {
        m_handleFile = false;
        m_UploadFileThread_->detach();
    }
    curl_easy_cleanup(m_upload_curl);
}

int32_t StoreFile::init(const store_file_info &fileinfo)
{
    m_storeFileInfo = fileinfo;
    m_Uploadfile_ = fileinfo.upload_file;
    m_uploadData = fileinfo.upload_data;
    m_SensorName_ = fileinfo.sensor_name;
    // 1、建立数据保存线程，用于控制CSV文件的创建时机，以及数据的保存
    m_FileDir_ = fileinfo.file_dir;
    m_handleData = true;
    m_handleFile = true;
    m_UploadFileThread_.reset(new std::thread([this]
                                        { HandleFileFunc(); }));
    m_HandleDataThread_.reset(new std::thread([this]
                                        { handleData(); }));

    // readJsonFile(PLATFORM_URLCONFIG_FILE, m_platform_url_);

    if (m_uploadData) {
        int32_t ret = initWebSocket();
        if (ret < 0) {
            Common_Log_e("initWebSocket error ret:%d", ret);
            return ret;
        }
    }

    json historyFile;
    readJsonFile(HISTORY_FILE, historyFile);
    m_HistoryFileList_ =  jsonToList(historyFile);
    if (m_HistoryFileList_.size() > 0) {
        wakeupHistoryUploading();
    }

    return 0;
}

int32_t StoreFile::initWebSocket()
{
    m_upload_curl = curl_easy_init();
    if (m_upload_curl)
    {
        // std::string updataUrl = m_platform_url_["UPLOADDATAURL"];
        std::string updataUrl = m_storeFileInfo.wsUrl;
        if (updataUrl == "") {
            updataUrl = "ws://180.76.250.75:8088";
        }
        printf("updataUrl :%s\n", updataUrl.c_str());
        curl_easy_setopt(m_upload_curl, CURLOPT_URL, updataUrl.c_str());
        curl_easy_setopt(m_upload_curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
        // curl_easy_setopt(m_upload_curl, CURLOPT_CONNECTTIMEOUT, 2);
        curl_easy_setopt(m_upload_curl, CURLOPT_TIMEOUT, 2);

        /* Perform the request, res gets the return code */
        CURLcode res = curl_easy_perform(m_upload_curl);
        if (res != CURLE_OK)
        {
            Common_Log_e("web connect fail res:%d\n", res);
            return -1;
        }
    }

    return 0;
}

int32_t StoreFile::deInitWebSocket()
{
    size_t sent;
    (void)curl_ws_send(m_upload_curl, "", 0, &sent, 0, CURLWS_CLOSE);
    curl_easy_cleanup(m_upload_curl);

    return 0;
}

void StoreFile::addData(const SensorDataInfo::CommonSensor &data)
{
    if (m_DataArray_.size() >= MAX_ARRAY_SIZE)
    {
        std::unique_lock<std::mutex> lock(m_Mutex_);
        m_DataArray_.pop_front();
        m_DataArray_.push_back(data);
        Common_Log_e("array space is not enough");
        return;
    }

    std::unique_lock<std::mutex> lock(m_Mutex_);
    m_DataArray_.push_back(data);
    m_Condition_.notify_one();
}

void StoreFile::saveData(const SensorDataInfo::CommonSensor &data,bool data_empty )
{
    // 做时间判断，如果间隔三分钟，则重新创建CSV文件
    // 保存数据到CSV文件
    int64_t curtime = Common_get_sys_time_sec();

    if (curtime - m_lastUpfileTime_ >= RECORD_INTERVAL || curtime - m_lastUpfileTime_ < 0)
    {
        m_lastUpfileTime_ = curtime;
        if (m_File_.is_open())
        {
            m_File_.close();
            // 上传文件
            if (m_LastFileName_ != "")
            {
                std::string savefile = FILE_PATH_STR + m_LastFileName_;
                bool ret = AdduploadFile(savefile);
                if (!ret)
                {
                    saveHistoryFile(savefile);
                }
            }
        }

        if (!data_empty) {
            // 重新创建CSV文件
            m_LastFileName_ = "/" + m_FileDir_ + "/" + Common_get_sys_time() + "_" + m_SensorName_ +".csv";
            Common_Log_i("create new csv file %s", m_LastFileName_.c_str());
            std::string savefiledir = FILE_PATH_STR + m_FileDir_;
            std::string createdircmd = "sudo mkdir -p " + savefiledir;
            std::string savefile = FILE_PATH_STR + m_LastFileName_;
            system(createdircmd.c_str());
            m_File_.open(savefile);
            saveHead();
        }
    }

    if( false == data_empty  )
    {
        saveBody(data);
    }
    else
    {
        Common_Log_i("---> Timeout to upload file %s", m_LastFileName_.c_str());
    }
}

void StoreFile::uploadData(const SensorDataInfo::CommonSensor &data)
{
    json body;
    packageData(data, body);
    // websocket上传数据
    size_t sent;
    CURLcode result =
        curl_ws_send(m_upload_curl, body.dump().c_str(), body.dump().length(), &sent, 0,
                     CURLWS_TEXT);
    if (result != CURLE_OK) {
        Common_Log_e("curl_ws_send fail result:%d\n", result);
        int32_t ret = deInitWebSocket();
        if (ret < 0) {
            Common_Log_e("deInitWebSocket error ret:%d", ret);
            return;
        }
        ret = initWebSocket();
        if (ret < 0) {
            Common_Log_e("initWebSocket error ret:%d", ret);
            return;
        }
    } else if (Common_get_sys_time_sec() - m_lastUpdataTime_ > 60 || Common_get_sys_time_sec() < m_lastUpdataTime_) {
        m_lastUpdataTime_ = Common_get_sys_time_sec();
        Common_Log_e("curl_ws_send success");
    }
}

void StoreFile::packageData(const SensorDataInfo::CommonSensor &data, json &packData)
{
    packData["DATA_SOURCE"] = "DATAMODULE";
    packData["TIMESTAMP"] = std::string(data.hourtime);
    packData["CURTIME"] = Common_get_sys_time_msec()/1000;
    packData["RECVTIME"] = data.recvtime;
    packData["ROTATIONSPEED"] = data.rotationSpeed;
    packData["POWER"] = data.power;
    packData["WINSPEED"] = data.windSpeed;

    std::stringstream strCpuId;
    strCpuId << std::hex << std::uppercase << std::setw(8) << std::setfill('0') << data.cpuID;
    std::stringstream strMccAddr;
    strMccAddr << std::hex << std::uppercase << std::setw(16) << std::setfill('0') << data.mccAddr;
    packData["CPUID"] = strCpuId.str();
    packData["MCCADDR"] = data.mccAddr;
    uint8_t chan = 0;
    uint8_t chanIndex = 0;
    while (chan < 4) {
      if ((data.devChan & (0x1 << chan)) > 0) {
        packData["CHAN"][chanIndex] = chan;
        chanIndex++;
      }
      chan++;
    }

    packData["ACCX"]["rawValue"] = data.accX.rawValue.empty()?0:data.accX.rawValue[0];
    packData["ACCX"]["maxValue"] = data.accX.maxValue;
    packData["ACCX"]["minValue"] = data.accX.minValue;
    packData["ACCX"]["peakValue"] = data.accX.peakValue;
    packData["ACCX"]["averageValue"] = data.accX.averageValue;
    packData["ACCX"]["absAverageValue"] = data.accX.absAverageValue;
    packData["ACCX"]["variance"] = data.accX.variance;
    packData["ACCX"]["standardDeviation"] = data.accX.standardDeviation;
    packData["ACCX"]["kurtosis"] = data.accX.kurtosis;
    packData["ACCX"]["margin"] = data.accX.margin;
    packData["ACCX"]["waveFactor"] = data.accX.waveFactor;
    packData["ACCX"]["peakFactor"] = data.accX.peakFactor;
    packData["ACCX"]["pulseFactor"] = data.accX.pulseFactor;
    packData["ACCX"]["mainFrequency"] = data.accX.mainFrequency;
    packData["ACCX"]["mainAmp"] = data.accX.mainAmp;

    packData["ACCY"]["rawValue"] = data.accY.rawValue.empty()?0:data.accY.rawValue[0];
    packData["ACCY"]["maxValue"] = data.accY.maxValue;
    packData["ACCY"]["minValue"] = data.accY.minValue;
    packData["ACCY"]["peakValue"] = data.accY.peakValue;
    packData["ACCY"]["averageValue"] = data.accY.averageValue;
    packData["ACCY"]["absAverageValue"] = data.accY.absAverageValue;
    packData["ACCY"]["variance"] = data.accY.variance;
    packData["ACCY"]["standardDeviation"] = data.accY.standardDeviation;
    packData["ACCY"]["kurtosis"] = data.accY.kurtosis;
    packData["ACCY"]["margin"] = data.accY.margin;
    packData["ACCY"]["waveFactor"] = data.accY.waveFactor;
    packData["ACCY"]["peakFactor"] = data.accY.peakFactor;
    packData["ACCY"]["pulseFactor"] = data.accY.pulseFactor;
    packData["ACCY"]["mainFrequency"] = data.accY.mainFrequency;
    packData["ACCY"]["mainAmp"] = data.accY.mainAmp;

    packData["ACCZ"]["rawValue"] = data.accZ.rawValue.empty()?0:data.accZ.rawValue[0];
    packData["ACCZ"]["maxValue"] = data.accZ.maxValue;
    packData["ACCZ"]["minValue"] = data.accZ.minValue;
    packData["ACCZ"]["peakValue"] = data.accZ.peakValue;
    packData["ACCZ"]["averageValue"] = data.accZ.averageValue;
    packData["ACCZ"]["absAverageValue"] = data.accZ.absAverageValue;
    packData["ACCZ"]["variance"] = data.accZ.variance;
    packData["ACCZ"]["standardDeviation"] = data.accZ.standardDeviation;
    packData["ACCZ"]["kurtosis"] = data.accZ.kurtosis;
    packData["ACCZ"]["margin"] = data.accZ.margin;
    packData["ACCZ"]["waveFactor"] = data.accZ.waveFactor;
    packData["ACCZ"]["peakFactor"] = data.accZ.peakFactor;
    packData["ACCZ"]["pulseFactor"] = data.accZ.pulseFactor;
    packData["ACCZ"]["mainFrequency"] = data.accZ.mainFrequency;
    packData["ACCZ"]["mainAmp"] = data.accZ.mainAmp;

    packData["SPEEDX"]["rawValue"] = data.speedX.rawValue.empty()?0:data.speedX.rawValue[0];
    packData["SPEEDX"]["maxValue"] = data.speedX.maxValue;
    packData["SPEEDX"]["minValue"] = data.speedX.minValue;
    packData["SPEEDX"]["peakValue"] = data.speedX.peakValue;
    packData["SPEEDX"]["averageValue"] = data.speedX.averageValue;
    packData["SPEEDX"]["absAverageValue"] = data.speedX.absAverageValue;
    packData["SPEEDX"]["variance"] = data.speedX.variance;
    packData["SPEEDX"]["standardDeviation"] = data.speedX.standardDeviation;
    packData["SPEEDX"]["kurtosis"] = data.speedX.kurtosis;
    packData["SPEEDX"]["margin"] = data.speedX.margin;
    packData["SPEEDX"]["waveFactor"] = data.speedX.waveFactor;
    packData["SPEEDX"]["peakFactor"] = data.speedX.peakFactor;
    packData["SPEEDX"]["pulseFactor"] = data.speedX.pulseFactor;
    packData["SPEEDX"]["mainFrequency"] = data.speedX.mainFrequency;
    packData["SPEEDX"]["mainAmp"] = data.speedX.mainAmp;

    packData["SPEEDY"]["rawValue"] = data.speedY.rawValue.empty()?0:data.speedY.rawValue[0];
    packData["SPEEDY"]["maxValue"] = data.speedY.maxValue;
    packData["SPEEDY"]["minValue"] = data.speedY.minValue;
    packData["SPEEDY"]["peakValue"] = data.speedY.peakValue;
    packData["SPEEDY"]["averageValue"] = data.speedY.averageValue;
    packData["SPEEDY"]["absAverageValue"] = data.speedY.absAverageValue;
    packData["SPEEDY"]["variance"] = data.speedY.variance;
    packData["SPEEDY"]["standardDeviation"] = data.speedY.standardDeviation;
    packData["SPEEDY"]["kurtosis"] = data.speedY.kurtosis;
    packData["SPEEDY"]["margin"] = data.speedY.margin;
    packData["SPEEDY"]["waveFactor"] = data.speedY.waveFactor;
    packData["SPEEDY"]["peakFactor"] = data.speedY.peakFactor;
    packData["SPEEDY"]["pulseFactor"] = data.speedY.pulseFactor;
    packData["SPEEDY"]["mainFrequency"] = data.speedY.mainFrequency;
    packData["SPEEDY"]["mainAmp"] = data.speedY.mainAmp;

    packData["SPEEDZ"]["rawValue"] = data.speedZ.rawValue.empty()?0:data.speedZ.rawValue[0];
    packData["SPEEDZ"]["maxValue"] = data.speedZ.maxValue;
    packData["SPEEDZ"]["minValue"] = data.speedZ.minValue;
    packData["SPEEDZ"]["peakValue"] = data.speedZ.peakValue;
    packData["SPEEDZ"]["averageValue"] = data.speedZ.averageValue;
    packData["SPEEDZ"]["absAverageValue"] = data.speedZ.absAverageValue;
    packData["SPEEDZ"]["variance"] = data.speedZ.variance;
    packData["SPEEDZ"]["standardDeviation"] = data.speedZ.standardDeviation;
    packData["SPEEDZ"]["kurtosis"] = data.speedZ.kurtosis;
    packData["SPEEDZ"]["margin"] = data.speedZ.margin;
    packData["SPEEDZ"]["waveFactor"] = data.speedZ.waveFactor;
    packData["SPEEDZ"]["peakFactor"] = data.speedZ.peakFactor;
    packData["SPEEDZ"]["pulseFactor"] = data.speedZ.pulseFactor;
    packData["SPEEDZ"]["mainFrequency"] = data.speedZ.mainFrequency;
    packData["SPEEDZ"]["mainAmp"] = data.speedZ.mainAmp;

    packData["MOVEX"]["rawValue"] = data.moveX.rawValue.empty()?0:data.moveX.rawValue[0];
    packData["MOVEX"]["maxValue"] = data.moveX.maxValue;
    packData["MOVEX"]["minValue"] = data.moveX.minValue;
    packData["MOVEX"]["peakValue"] = data.moveX.peakValue;
    packData["MOVEX"]["averageValue"] = data.moveX.averageValue;
    packData["MOVEX"]["absAverageValue"] = data.moveX.absAverageValue;
    packData["MOVEX"]["variance"] = data.moveX.variance;
    packData["MOVEX"]["standardDeviation"] = data.moveX.standardDeviation;
    packData["MOVEX"]["kurtosis"] = data.moveX.kurtosis;
    packData["MOVEX"]["margin"] = data.moveX.margin;
    packData["MOVEX"]["waveFactor"] = data.moveX.waveFactor;
    packData["MOVEX"]["peakFactor"] = data.moveX.peakFactor;
    packData["MOVEX"]["pulseFactor"] = data.moveX.pulseFactor;
    packData["MOVEX"]["mainFrequency"] = data.moveX.mainFrequency;
    packData["MOVEX"]["mainAmp"] = data.moveX.mainAmp;

    packData["MOVEY"]["rawValue"] = data.moveY.rawValue.empty()?0:data.moveY.rawValue[0];
    packData["MOVEY"]["maxValue"] = data.moveY.maxValue;
    packData["MOVEY"]["minValue"] = data.moveY.minValue;
    packData["MOVEY"]["peakValue"] = data.moveY.peakValue;
    packData["MOVEY"]["averageValue"] = data.moveY.averageValue;
    packData["MOVEY"]["absAverageValue"] = data.moveY.absAverageValue;
    packData["MOVEY"]["variance"] = data.moveY.variance;
    packData["MOVEY"]["standardDeviation"] = data.moveY.standardDeviation;
    packData["MOVEY"]["kurtosis"] = data.moveY.kurtosis;
    packData["MOVEY"]["margin"] = data.moveY.margin;
    packData["MOVEY"]["waveFactor"] = data.moveY.waveFactor;
    packData["MOVEY"]["peakFactor"] = data.moveY.peakFactor;
    packData["MOVEY"]["pulseFactor"] = data.moveY.pulseFactor;
    packData["MOVEY"]["mainFrequency"] = data.moveY.mainFrequency;
    packData["MOVEY"]["mainAmp"] = data.moveY.mainAmp;

    packData["MOVEZ"]["rawValue"] = data.moveZ.rawValue.empty()?0:data.moveZ.rawValue[0];
    packData["MOVEZ"]["maxValue"] = data.moveZ.maxValue;
    packData["MOVEZ"]["minValue"] = data.moveZ.minValue;
    packData["MOVEZ"]["peakValue"] = data.moveZ.peakValue;
    packData["MOVEZ"]["averageValue"] = data.moveZ.averageValue;
    packData["MOVEZ"]["absAverageValue"] = data.moveZ.absAverageValue;
    packData["MOVEZ"]["variance"] = data.moveZ.variance;
    packData["MOVEZ"]["standardDeviation"] = data.moveZ.standardDeviation;
    packData["MOVEZ"]["kurtosis"] = data.moveZ.kurtosis;
    packData["MOVEZ"]["margin"] = data.moveZ.margin;
    packData["MOVEZ"]["waveFactor"] = data.moveZ.waveFactor;
    packData["MOVEZ"]["peakFactor"] = data.moveZ.peakFactor;
    packData["MOVEZ"]["pulseFactor"] = data.moveZ.pulseFactor;
    packData["MOVEZ"]["mainFrequency"] = data.moveZ.mainFrequency;
    packData["MOVEZ"]["mainAmp"] = data.moveZ.mainAmp;

    return;
}

void StoreFile::saveHead()
{
    m_File_ << m_SensorName_ << ", , , ,";
    m_File_ << "加速度x轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << "加速度y轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << "加速度z轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << "速度x轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << "速度y轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << "速度z轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << "位移x轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << "位移y轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << "位移z轴";
    for (int index = 0; index < 15; index++)
    {
        m_File_ << ", ";
    }
    m_File_ << std::endl;
    m_File_ << "时间戳" << "," << "转速" << "," << "功率" << "," << "风速" << ",";
    for (int item = 0; item < 9; item++)
    {
        m_File_ << "原始数据" << "," << "最大值" << "," << "最小值" << "," << "峰峰值" << "," << "平均值" << ",";
        m_File_ << "绝对平均值" << "," << "方差" << "," << "标准差" << "," << "峭度" << "," << "裕度" << ",";
        m_File_ << "波形因子" << "," << "峰值因子" << "," << "脉冲因子" << "," << "主要频率" << "," << "主要振幅" << ",";
    }
    m_File_ << std::endl;

    return;
}

void StoreFile::saveRawDataArray(std::vector<float> rawdataList)
{
    if (rawdataList.size() == 0)
    {
        m_File_ << 0 << ",";
        return;
    }
    m_File_ << "\"" << rawdataList[0];
    for (int index = 1; index < rawdataList.size(); index ++) {
        m_File_ << "|" << rawdataList[index];
    }
    m_File_ << "\"" << ",";
}

void StoreFile::saveBody(const SensorDataInfo::CommonSensor &data)
{
    m_File_ << data.calendartime << "," << data.rotationSpeed << "," << data.power << "," << data.windSpeed << ",";
    saveRawDataArray(data.accX.rawValue);
    m_File_ << data.accX.maxValue << "," << data.accX.minValue << "," << data.accX.peakValue << ",";
    m_File_ << data.accX.averageValue << "," << data.accX.absAverageValue << "," << data.accX.variance << "," << data.accX.standardDeviation << ",";
    m_File_ << data.accX.kurtosis << "," << data.accX.margin << "," << data.accX.waveFactor << "," << data.accX.peakFactor << ",";
    m_File_ << data.accX.pulseFactor << "," << data.accX.mainFrequency << "," << data.accX.mainAmp << ",";

    saveRawDataArray(data.accY.rawValue);
    m_File_ << data.accY.maxValue << "," << data.accY.minValue << "," << data.accY.peakValue << ",";
    m_File_ << data.accY.averageValue << "," << data.accY.absAverageValue << "," << data.accY.variance << "," << data.accY.standardDeviation << ",";
    m_File_ << data.accY.kurtosis << "," << data.accY.margin << "," << data.accY.waveFactor << "," << data.accY.peakFactor << ",";
    m_File_ << data.accY.pulseFactor << "," << data.accY.mainFrequency << "," << data.accY.mainAmp << ",";

    saveRawDataArray(data.accZ.rawValue);
    m_File_ << data.accZ.maxValue << "," << data.accZ.minValue << "," << data.accZ.peakValue << ",";
    m_File_ << data.accZ.averageValue << "," << data.accZ.absAverageValue << "," << data.accZ.variance << "," << data.accZ.standardDeviation << ",";
    m_File_ << data.accZ.kurtosis << "," << data.accZ.margin << "," << data.accZ.waveFactor << "," << data.accZ.peakFactor << ",";
    m_File_ << data.accZ.pulseFactor << "," << data.accZ.mainFrequency << "," << data.accZ.mainAmp << ",";

    saveRawDataArray(data.speedX.rawValue);
    m_File_ << data.speedX.maxValue << "," << data.speedX.minValue << "," << data.speedX.peakValue << ",";
    m_File_ << data.speedX.averageValue << "," << data.speedX.absAverageValue << "," << data.speedX.variance << "," << data.speedX.standardDeviation << ",";
    m_File_ << data.speedX.kurtosis << "," << data.speedX.margin << "," << data.speedX.waveFactor << "," << data.speedX.peakFactor << ",";
    m_File_ << data.speedX.pulseFactor << "," << data.speedX.mainFrequency << "," << data.speedX.mainAmp << ",";

    saveRawDataArray(data.speedY.rawValue);
    m_File_ << data.speedY.maxValue << "," << data.speedY.minValue << "," << data.speedY.peakValue << ",";
    m_File_ << data.speedY.averageValue << "," << data.speedY.absAverageValue << "," << data.speedY.variance << "," << data.speedY.standardDeviation << ",";
    m_File_ << data.speedY.kurtosis << "," << data.speedY.margin << "," << data.speedY.waveFactor << "," << data.speedY.peakFactor << ",";
    m_File_ << data.speedY.pulseFactor << "," << data.speedY.mainFrequency << "," << data.speedY.mainAmp << ",";

    saveRawDataArray(data.speedZ.rawValue);
    m_File_ << data.speedZ.maxValue << "," << data.speedZ.minValue << "," << data.speedZ.peakValue << ",";
    m_File_ << data.speedZ.averageValue << "," << data.speedZ.absAverageValue << "," << data.speedZ.variance << "," << data.speedZ.standardDeviation << ",";
    m_File_ << data.speedZ.kurtosis << "," << data.speedZ.margin << "," << data.speedZ.waveFactor << "," << data.speedZ.peakFactor << ",";
    m_File_ << data.speedZ.pulseFactor << "," << data.speedZ.mainFrequency << "," << data.speedZ.mainAmp << ",";

    saveRawDataArray(data.moveX.rawValue);
    m_File_ << data.moveX.maxValue << "," << data.moveX.minValue << "," << data.moveX.peakValue << ",";
    m_File_ << data.moveX.averageValue << "," << data.moveX.absAverageValue << "," << data.moveX.variance << "," << data.moveX.standardDeviation << ",";
    m_File_ << data.moveX.kurtosis << "," << data.moveX.margin << "," << data.moveX.waveFactor << "," << data.moveX.peakFactor << ",";
    m_File_ << data.moveX.pulseFactor << "," << data.moveX.mainFrequency << "," << data.moveX.mainAmp << ",";

    saveRawDataArray(data.moveY.rawValue);
    m_File_ << data.moveY.maxValue << "," << data.moveY.minValue << "," << data.moveY.peakValue << ",";
    m_File_ << data.moveY.averageValue << "," << data.moveY.absAverageValue << "," << data.moveY.variance << "," << data.moveY.standardDeviation << ",";
    m_File_ << data.moveY.kurtosis << "," << data.moveY.margin << "," << data.moveY.waveFactor << "," << data.moveY.peakFactor << ",";
    m_File_ << data.moveY.pulseFactor << "," << data.moveY.mainFrequency << "," << data.moveY.mainAmp << ",";

    saveRawDataArray(data.moveZ.rawValue);
    m_File_ << data.moveZ.maxValue << "," << data.moveZ.minValue << "," << data.moveZ.peakValue << ",";
    m_File_ << data.moveZ.averageValue << "," << data.moveZ.absAverageValue << "," << data.moveZ.variance << "," << data.moveZ.standardDeviation << ",";
    m_File_ << data.moveZ.kurtosis << "," << data.moveZ.margin << "," << data.moveZ.waveFactor << "," << data.moveZ.peakFactor << ",";
    m_File_ << data.moveZ.pulseFactor << "," << data.moveZ.mainFrequency << "," << data.moveZ.mainAmp << std::endl;

    return;
}

void StoreFile::handleData()
{
    bool data_empty = false;
    
    while (m_handleData)
    {
        SensorDataInfo::CommonSensor sensorData;
        data_empty = false;
        if ( m_DataArray_.empty() )
        {
            std::unique_lock<std::mutex> lock(m_Mutex_);
            if(  std::cv_status::timeout == m_Condition_.wait_for(lock, std::chrono::seconds(RECORD_INTERVAL)) )  
            {
                data_empty = true;
            }
        }

        if ( false == data_empty )
        {
            std::unique_lock<std::mutex> lock(m_Mutex_);
            sensorData = m_DataArray_.front();
            m_DataArray_.pop_front();
            lock.unlock();
        }

        if (m_uploadData && false == data_empty)
        {
            uploadData(sensorData); // ws
        }

        if (m_Uploadfile_)
        {
            saveData(sensorData,data_empty); //save file and upload file to minios
        }

        if (m_HistoryFileList_.size() > 0)
        {
            wakeupHistoryUploading();
        }
    }
}

void StoreFile::setUploadFlag(bool flag)
{
    if (flag == m_Uploadfile_)
    {
        return;
    }
    m_Uploadfile_ = flag;
}

void StoreFile::uploadFileImmediate()
{
    if (m_File_.is_open())
    {
        m_File_.close();
    }

    // 上传文件
    if (m_LastFileName_ != "")
    {
        if (m_Uploadfile_)
        {
            std::string savefile = FILE_PATH_STR + m_LastFileName_;
            bool ret = uploadFile(savefile);
            if (!ret) {
                saveHistoryFile(savefile);
            }
        }
        else
        {
            saveHistoryFile(m_LastFileName_);
        }
    }
}

void StoreFile::wakeupHistoryUploading()
{
    if (m_UploadHistoryfile_ == false) {
        m_UploadHistoryfile_ = true;
        m_HistoryThread_.reset(new std::thread([this]
                                           { uploadHistoryFile(); }));
        m_HistoryThread_->detach();
    }
}

bool StoreFile::AdduploadFile(const std::string &filename)
{
    std::unique_lock<std::mutex> lock(m_FileMutex_);
    m_FileList_.push_back(filename);
    Common_Log_e("m_FileList_ size:%d\n", m_FileList_.size());
    lock.unlock();

    return true;
}

bool StoreFile::uploadFile(const std::string &filename)
{
    // std::string server = m_platform_url_["UPLOADFILEURL"];
    // const char *access_key = "edge";
    // const char *secret_key = "2xxhfy5ZE7j.vji";
    std::string server = m_storeFileInfo.minioEndPoint;
    std::string access_key = m_storeFileInfo.minioAccessKey;
    std::string secret_key = m_storeFileInfo.minioSecretKey;
    MinioClient minio(server, access_key, secret_key);

    int pos = filename.rfind("/");
    std::string minioFileName =  "/" + m_FileDir_ + "/" + filename.substr(pos + 1);
    std::string miniFilePath = m_storeFileInfo.coreCpuid + "/" + m_storeFileInfo.storeCpuID + minioFileName;
    if (minio.upload_file(iLogger::format("/%s/%s", m_storeFileInfo.minioBucketName.c_str(), miniFilePath.c_str()), filename.c_str()))
    {
        Common_Log_e("upload %s success, size: %d bytes", filename.c_str(), iLogger::file_size(filename));
        json replyInfo = json::parse(m_storeFileInfo.jsonInfo);
        replyInfo["data"]["coreCpuId"] = replyInfo["params"]["coreCpuId"];
        replyInfo["data"]["storeCpuId"] = replyInfo["params"]["storeCpuId"];
        replyInfo["data"]["storeTaskId"] = replyInfo["params"]["storeTaskId"];
        replyInfo["data"]["mccAddress"] = replyInfo["params"]["mcc_address"];
        replyInfo["data"]["ch_param"] = replyInfo["params"]["ch_param"];
        replyInfo["data"]["sn"] = replyInfo["params"]["sn"];
        replyInfo["data"]["URL"] = "/" + m_storeFileInfo.minioBucketName + "/" + miniFilePath;
        replyInfo["subcmd"] = "uploadFileEnd";
        replyInfo["code"] = 200;
        replyInfo["result"] = "success";
        replyInfo.erase("params");
        StoreTaskManager::GetInstance()->PubUploadFileEndInfo(replyInfo);
    }
    else
    {
        Common_Log_e("upload %s fail", filename.c_str());
        return false;
    }
    return true;
}

void StoreFile::HandleFileFunc()
{
    while (m_handleFile)
    {
        if (m_FileList_.empty())
        {
            sleep(2);
			continue;
        }

        std::unique_lock<std::mutex> lock(m_FileMutex_);
        std::string uploadFileName = m_FileList_.front();
        m_FileList_.pop_front();
        lock.unlock();

        bool ret = uploadFile(uploadFileName);
        if (!ret)
        {
            saveHistoryFile(uploadFileName);
        }
    }
}

void StoreFile::uploadHistoryFile()
{
    while (m_UploadHistoryfile_)
    {
        if (m_HistoryFileList_.empty())
        {
            break;
        }

        std::unique_lock<std::mutex> lock(m_HistoryMutex_);
        std::string filename = m_HistoryFileList_.front();
        bool ret = uploadFile(filename);
        if (ret) {
            m_HistoryFileList_.pop_front();
        }
        lock.unlock();
        usleep(100000);
    }

    json filelist = listToJson(m_HistoryFileList_);
    writeJsonFile(HISTORY_FILE, filelist);
    m_UploadHistoryfile_ = false;
}

void StoreFile::saveHistoryFile(const std::string &filename)
{
    std::unique_lock<std::mutex> lock(m_HistoryMutex_);
    m_HistoryFileList_.push_back(filename);
    lock.unlock();
}

json StoreFile::listToJson(const std::list<std::string> &list)
{
    json retvalue;
    int32_t index = 0;
    if (!list.empty())
    {
        for (auto &it : list)
        {
            retvalue["HISTORYFILE"][index] = it;
            index++;
        }
    }
    return retvalue;
}

std::list<std::string> StoreFile::jsonToList(json objjson)
{
    std::list<std::string> templist;
    for (int index = 0; index < objjson["HISTORYFILE"].size(); index++)
    {
        templist.push_back(objjson["HISTORYFILE"][index]);
    }
    return templist;
}

void StoreFile::writeJsonFile(const std::string &filename, const json &objjson)
{
    std::ofstream file(filename);
    if (!file.is_open())
    {
        file.open(filename, std::fstream::app);
    }
    file << objjson.dump(4);

    return;
}

void StoreFile::readJsonFile(const std::string &filename, json &objjson)
{
    std::fstream file(filename);
    if (!file.is_open())
    {
        Common_Log_e("filename:%s open fail", filename.c_str());
        return;
    }
    file >> objjson;

    return;
}